/* Parallel Elliptic Curve Cryptography Engine - An OpenSSL Engine which
 * uses the SPU Elliptic Curve Library to provide optimized functionality
 * on the CBEA.
 *
 * Copyright (C) 2008  Michael Annichiarico (mike.gcdeveloper@gmail.com)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/engine.h>

#ifndef OPENSSL_NO_HW
#if /*defined(OPENSSL_USE_PECC) &&*/ !defined(OPENSSL_NO_HW_PECC)

#include "e_pecc_err.h"


#define E_PECC_LIB_NAME "CellBE Parallel ECC Engine"
#include "e_pecc_err.c"

static int e_pecc_bind_helper(ENGINE *e);
static int e_pecc_destroy(ENGINE *e);
static int e_pecc_init(ENGINE *e);
static int e_pecc_finish(ENGINE *e);
static int e_pecc_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); 
static int pecc_init(ENGINE *e);
static int pecc_fini(ENGINE *e);

/* The definitions for control commands specific to this engine */
/* #define E_PECC_CMD_SO_PATH		ENGINE_CMD_BASE */
static const ENGINE_CMD_DEFN e_pecc_cmd_defns[] = {
#if 0
	{E_PECC_CMD_SO_PATH,
		"SO_PATH",
		"Specifies the path to the 'e_pecc' shared library",
		ENGINE_CMD_FLAG_STRING},
#endif
	{0, NULL, NULL, 0}
	};

static ENGINE *engine_pecc(void)
	{
	ENGINE *ret = ENGINE_new();
	if(!ret)
		return NULL;
	if(!e_pecc_bind_helper(ret))
		{
		ENGINE_free(ret);
		return NULL;
		}
	return ret;
	}

void ENGINE_load_pecc(void)
	{
	/* Copied from eng_[openssl|dyn].c */
	ENGINE *toadd = engine_pecc();
	if(!toadd) return;
	ENGINE_add(toadd);
	ENGINE_free(toadd);
	ERR_clear_error();
	}

static int e_pecc_destroy(ENGINE *e)
	{
	ERR_unload_PECC_strings();
	return 1;
	}

/* (de)initialisation functions. */
static int e_pecc_init(ENGINE *e)
	{
	return(pecc_init(e));
	}

static int e_pecc_finish(ENGINE *e)
	{
	return(pecc_fini(e));
	}

static int e_pecc_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
	{
	int to_return = 1;

	switch(cmd)
		{
#if 0
	case E_PECC_CMD_SO_PATH:
		/* ... */
#endif
	/* The command isn't understood by this engine */
	default:
		PECCerr(PECC_F_E_PECC_CTRL,
			PECC_R_CTRL_COMMAND_NOT_IMPLEMENTED);
		to_return = 0;
		break;
		}

	return to_return;
	}

/* -------------------- ACTUAL ENGINE IMPLEMENTATION -----------------------*/

#include "e_pecc_impl.c"

/* -------------------- END ACTUAL ENGINE IMPLEMENTATION -----------------------*/

/* This stuff is needed if this ENGINE is being compiled into a self-contained
 * shared-library. */	   
#ifdef ENGINE_DYNAMIC_SUPPORT

static int bind_fn(ENGINE *e, const char *id)
	{
	if(id && (strcmp(id, engine_e_pecc_id) != 0))
		return 0;
	if(!e_pecc_bind_helper(e))
		return 0;
	return 1;
	}       
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
#endif /* ENGINE_DYNAMIC_SUPPORT */

#endif /* !OPENSSL_NO_HW_PECC */
#endif /* !OPENSSL_NO_HW */

